﻿using System;
using System.Collections.Generic;
#if __IOS__
using ILRuntime.Reflection;
#endif

namespace mb
{
    public sealed class ServiceLocator
    {
        static readonly Lazy<ServiceLocator> instance = new Lazy<ServiceLocator>(() => new ServiceLocator());
        readonly Dictionary<string, Lazy<object>> registeredServices = new Dictionary<string, Lazy<object>>();

        public static ServiceLocator Instance => instance.Value;
        public static bool SilentError = false;

        public void Register<TContract, TService>() //where TService : new()
        {
            Register(typeof(TContract).ToString(), typeof(TService));

        }

        public void Register(string name, Type type) //where TService : new()
        {
            Console.WriteLine("register service {0}->{1}", name, type);
            registeredServices[name] =
                new Lazy<object>(() =>
                {
#if __IOS__
                    if (type is ILRuntimeType || type is ILRuntimeWrapperType)
                    {
                        return Instance.Get<IHotLoader>().CreateInstance(type.FullName);
                    }
                    else
                    {
                        return Activator.CreateInstance(type);
                    }
#else
                    return Activator.CreateInstance(type);
#endif
                });
        }

        public T Get<T>() where T : class
        {
            // Console.WriteLine(">>>>>>>>>>>>get service {0}", typeof(T).FullName);
#if __IOS__
            Type type = typeof(T);
            if (type is ILRuntimeType || type is ILRuntimeWrapperType)
            {
                return Get(type.FullName) as T;
            }
            else
            {
                return Get(typeof(T).ToString()) as T;
            }
#else
            return Get(typeof(T).ToString()) as T;
#endif
        }

        public static T SGet<T>() where T : class
        {
            Console.WriteLine("!!!!!!!!!!!!!get service {0}", typeof(T).FullName);
            return Instance.Get<T>();
        }

        public object Get(string type)
        {
            Lazy<object> service;
            if (registeredServices.TryGetValue(type, out service))
            {
                // Console.WriteLine("get service {0}", type);
                return service.Value;
            }

            if (SilentError) return null;
            throw new Exception("get none exist service:" + type);
        }
    }
}